class Lunar {
    constructor(date) {
        this.date = date;
    }

    static lunarInfo = [
        0x04bd8,0x04ae0,0x0a570,0x054d5,0x0d260,0x0d950,0x16554,0x056a0,0x09ad0,0x055d2,
        0x04ae0,0x0a5b6,0x0a4d0,0x0d250,0x1d255,0x0b540,0x0d6a0,0x0ada2,0x095b0,0x14977,
        0x04970,0x0a4b0,0x0b4b5,0x06a50,0x06d40,0x1ab54,0x02b60,0x09570,0x052f2,0x04970,
        0x06566,0x0d4a0,0x0ea50,0x06e95,0x05ad0,0x02b60,0x186e3,0x092e0,0x1c8d7,0x0c950,
        0x0d4a0,0x1d8a6,0x0b550,0x056a0,0x1a5b4,0x025d0,0x092d0,0x0d2b2,0x0a950,0x0b557,
        0x06ca0,0x0b550,0x15355,0x04da0,0x0a5b0,0x14573,0x052b0,0x0a9a8,0x0e950,0x06aa0,
        0x0aea6,0x0ab50,0x04b60,0x0aae4,0x0a570,0x05260,0x0f263,0x0d950,0x05b57,0x056a0,
        0x096d0,0x04dd5,0x04ad0,0x0a4d0,0x0d4d4,0x0d250,0x0d558,0x0b540,0x0b6a0,0x195a6,
        0x095b0,0x049b0,0x0a974,0x0a4b0,0x0b27a,0x06a50,0x06d40,0x0af46,0x0ab60,0x09570,
        0x04af5,0x04970,0x064b0,0x074a3,0x0ea50,0x06b58,0x055c0,0x0ab60,0x096d5,0x092e0,
        0x0c960,0x0d954,0x0d4a0,0x0da50,0x07552,0x056a0,0x0abb7,0x025d0,0x092d0,0x0cab5,
        0x0a950,0x0b4a0,0x0baa4,0x0ad50,0x055d9,0x04ba0,0x0a5b0,0x15176,0x052b0,0x0a930,
        0x07954,0x06aa0,0x0ad50,0x05b52,0x04b60,0x0a6e6,0x0a4e0,0x0d260,0x0ea65,0x0d530,
        0x05aa0,0x076a3,0x096d0,0x04bd7,0x04ad0,0x0a4d0,0x1d0b6,0x0d250,0x0d520,0x0dd45,
        0x0b5a0,0x056d0,0x055b2,0x049b0,0x0a577,0x0a4b0,0x0aa50,0x1b255,0x06d20,0x0ada0
    ];

    static Gan = ["甲","乙","丙","丁","戊","己","庚","辛","壬","癸"];
    static Zhi = ["子","丑","寅","卯","辰","巳","午","未","申","酉","戌","亥"];
    static Animals = ["鼠","牛","虎","兔","龙","蛇","马","羊","猴","鸡","狗","猪"];
    static lunarMonth = ['正','二','三','四','五','六','七','八','九','十','冬','腊'];
    static lunarDay = ['初一','初二','初三','初四','初五','初六','初七','初八','初九','初十',
        '十一','十二','十三','十四','十五','十六','十七','十八','十九','二十',
        '廿一','廿二','廿三','廿四','廿五','廿六','廿七','廿八','廿九','三十'];

    getLunarDate() {
        // 计算距离1900年1月31日的天数
        const baseDate = new Date(1900, 0, 31);
        let offset = Math.floor((this.date - baseDate) / 86400000);
        
        // 计算年份
        let year = 1900;
        for(let i = 0; i < Lunar.lunarInfo.length && offset > 0; i++) {
            const yearDays = this.getLunarYearDays(1900 + i);
            offset -= yearDays;
            year++;
        }
        
        if(offset < 0) {
            offset += this.getLunarYearDays(--year);
        }
        
        // 计算月份
        let isLeap = false;
        let month = 1;
        let temp = 0;
        const leapMonth = this.getLeapMonth(year);
        
        for(; month < 13 && offset > 0; month++) {
            // 闰月
            if(leapMonth > 0 && month === (leapMonth + 1) && !isLeap) {
                --month;
                isLeap = true;
                temp = this.getLeapDays(year);
            } else {
                temp = this.getLunarMonthDays(year, month);
            }
            
            if(isLeap && month === (leapMonth + 1)) {
                isLeap = false;
            }
            
            offset -= temp;
        }
        
        if(offset === 0 && leapMonth > 0 && month === leapMonth + 1) {
            if(isLeap) {
                isLeap = false;
            } else {
                isLeap = true;
                --month;
            }
        }
        
        if(offset < 0) {
            offset += temp;
            --month;
        }
        
        // 计算天数
        const day = offset + 1;
        
        // 计算天干地支年
        const yearGanIndex = (year - 4) % 10;
        const yearZhiIndex = (year - 4) % 12;
        
        return {
            year: year,
            month: month,
            day: day,
            isLeap: isLeap,
            yearCn: Lunar.Gan[yearGanIndex] + Lunar.Zhi[yearZhiIndex] + '年',
            monthCn: (isLeap ? '闰' : '') + Lunar.lunarMonth[month - 1] + '月',
            dayCn: Lunar.lunarDay[day - 1]
        };
    }

    getLunarYearDays(year) {
        let sum = 348;
        for(let i = 0x8000; i > 0x8; i >>= 1) {
            sum += (Lunar.lunarInfo[year - 1900] & i) ? 1 : 0;
        }
        return sum + this.getLeapDays(year);
    }

    getLeapMonth(year) {
        return Lunar.lunarInfo[year - 1900] & 0xf;
    }

    getLeapDays(year) {
        if(this.getLeapMonth(year)) {
            return (Lunar.lunarInfo[year - 1900] & 0x10000) ? 30 : 29;
        }
        return 0;
    }

    getLunarMonthDays(year, month) {
        return (Lunar.lunarInfo[year - 1900] & (0x10000 >> month)) ? 30 : 29;
    }
} 